﻿using System;
using System.Data;
using System.Configuration;
using System.Collections;
using System.Collections.Generic;
using System.DirectoryServices;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;
using System.Xml.Serialization;

namespace Vision.Core.ActivityComponents.ActiveDirectory
{
    [Serializable]
    public class ActiveDirectoryUserInfo
    {
        #region [ Fields ]
        public static readonly ActiveDirectoryUserInfo Empty = new ActiveDirectoryUserInfo();
        Dictionary<string, object> _properties;
        DirectoryEntry _manager = null;
        DirectoryEntry _employee;
        string[] _directReports;
        #endregion

        #region [ Constructor ]
        public ActiveDirectoryUserInfo(DirectoryEntry entry)
            : this()
        {
            _employee = entry;

            foreach (string key in _employee.Properties.PropertyNames)
            {
                object value = _employee.Properties[key].Value;
                SetProperty(key, value);
            }
        }
        public ActiveDirectoryUserInfo()
        {
            _properties = new Dictionary<string, object>();
        }
        #endregion

        #region [ GetDirectReports ]
        string[] GetDirectReports()
        {
            List<string> names = new List<string>();

            if (ADUserDirectoryEntry.Properties["directReports"].Value is object[])
            {
                object[] reports = (object[])ADUserDirectoryEntry.Properties["directReports"].Value;

                foreach (object report in reports)
                {
                    DirectoryEntry entry = new DirectoryEntry("LDAP://" + report.ToString());
                    names.Add(GetEntryFullName(entry));
                }
            }
            else if (BaseGet<string>("directreports").Length > 0)
            {
                string report = BaseGet<string>("directreports");
                DirectoryEntry entry = new DirectoryEntry("LDAP://" + report);
                names.Add(GetEntryFullName(entry));
            }

            return names.ToArray();
        }
        #endregion

        #region [ GetEntryFullName ]
        string GetEntryFullName(DirectoryEntry entry)
        {
            ActiveDirectoryUserInfo user = new ActiveDirectoryUserInfo(entry);
            return user.DisplayName;
        }
        #endregion

        #region [ BaseGet ]
        /// <summary>
        /// Gets a property value from the dictionary
        /// </summary>
        /// <param name="name"></param>
        /// <returns></returns>
        T BaseGet<T>(string name)
        {
            if (_properties.ContainsKey(name))
                return (T)_properties[name];
            return default(T);
        }
        #endregion

        #region [ SetProperty ]
        /// <summary>
        /// Adds a property to the Properties collection.
        /// </summary>
        /// <param name="name"></param>
        /// <param name="value"></param>
        internal void SetProperty(string name, object value)
        {
            _properties.Add(name.ToLower(), value);
        }
        #endregion

        #region [ Internal Properties ]
        #region [ Properties (Dictionary) ]
        internal Dictionary<string, object> Properties
        {
            get { return _properties; }
        }
        #endregion
        #endregion

        #region [ EmployeeEntry ]
        public DirectoryEntry ADUserDirectoryEntry
        {
            get { return _employee; }
        }
        #endregion

        #region [ ManagerEntry ]
        /// <summary>Gets/sets the employee's manager.</summary>
        public DirectoryEntry ManagerDirectoryEntry
        {
            get
            {
                if (_manager == null)
                {
                    if (string.IsNullOrEmpty(BaseGet<string>("manager"))) return null;

                    try
                    {
                        _manager = new DirectoryEntry("LDAP://" + BaseGet<string>("manager"));
                    }
                    catch { }
                }
                return _manager;
            }
        }
        #endregion

        #region [ Employee Properties ]
        #region [ Manager ]
        /// <summary>Gets/sets employee ID.</summary>
        [XmlAttribute("Manager")]
        public string Manager
        {
            get
            {
                if (ManagerDirectoryEntry == null)
                    return string.Empty;
                return GetEntryFullName(ManagerDirectoryEntry);
            }
            set { }
        }
        #endregion

        #region [ DirectReports ]
        /// <summary>Gets/sets display name.</summary>
        [XmlArray("DirectReports")]
        [XmlArrayItem("DirectReport")]
        public string[] DirectReports
        {
            get
            {
                if (_directReports == null)
                    _directReports = GetDirectReports();
                return _directReports;
            }
            set { _directReports = value; }
        }
        #endregion

        #region [ EmployeeID ]
        /// <summary>Gets/sets employee ID.</summary>
        [XmlAttribute("EmployeeID")]
        public string EmployeeID
        {
            get { return BaseGet<string>("employeeid"); }
            set { SetProperty("employeeid", value); }
        }
        #endregion

        #region [ LogonName ]
        /// <summary>Gets/sets logon name.</summary>
        [XmlAttribute("LogonName")]
        public string LogonName
        {
            get { return BaseGet<string>("samaccountname"); }
            set { SetProperty("samaccountname", value); }
        }
        #endregion

        #region [ FirstName ]
        /// <summary>Gets/sets first name.</summary>
        [XmlAttribute("FirstName")]
        public string FirstName
        {
            get { return BaseGet<string>("givenname"); }
            set { SetProperty("givenName", value); }
        }
        #endregion

        #region [ LastName ]
        /// <summary>Gets/sets last name.</summary>
        [XmlAttribute("LastName")]
        public string LastName
        {
            get { return BaseGet<string>("sn"); }
            set { SetProperty("sn", value); }
        }
        #endregion

        #region [ Title ]
        /// <summary>Gets/sets title.</summary>
        [XmlAttribute("Title")]
        public string Title
        {
            get { return BaseGet<string>("title"); }
            set { SetProperty("title", value); }
        }
        #endregion

        #region [ Description ]
        /// <summary>Gets/sets description.</summary>
        [XmlAttribute("Description")]
        public string Description
        {
            get { return BaseGet<string>("description"); }
            set { SetProperty("description", value); }
        }
        #endregion

        #region [ DisplayName ]
        /// <summary>Gets/sets display name.</summary>
        [XmlAttribute("DisplayName")]
        public string DisplayName
        {
            get { return BaseGet<string>("displayname"); }
            set { SetProperty("displayname", value); }
        }
        #endregion

        #region [ Office ]
        /// <summary>Gets/sets office.</summary>
        [XmlAttribute("Office")]
        public string Office
        {
            get { return BaseGet<string>("physicaldeliveryofficename"); }
            set { SetProperty("physicaldeliveryofficename", value); }
        }
        #endregion

        #region [ Company ]
        /// <summary>Gets/sets company.</summary>
        [XmlAttribute("Company")]
        public string Company
        {
            get { return BaseGet<string>("company"); }
            set { SetProperty("company", value); }
        }
        #endregion

        #region [ Email ]
        /// <summary>Gets/sets email address.</summary>
        [XmlAttribute("Email")]
        public string Email
        {
            get { return BaseGet<string>("mail"); }
            set { SetProperty("mail", value); }
        }
        #endregion

        #region [ StreetAddress ]
        /// <summary>Gets/sets street address.</summary>
        [XmlAttribute("StreetAddress")]
        public string StreetAddress
        {
            get { return BaseGet<string>("streetaddress"); }
            set { SetProperty("streetaddress", value); }
        }
        #endregion

        #region [ City ]
        /// <summary>Gets/sets city.</summary>
        [XmlAttribute("City")]
        public string City
        {
            get { return BaseGet<string>("l"); }
            set { SetProperty("l", value); }
        }
        #endregion

        #region [ State ]
        /// <summary>Gets/sets state.</summary>
        [XmlAttribute("State")]
        public string State
        {
            get { return BaseGet<string>("st"); }
            set { SetProperty("st", value); }
        }
        #endregion

        #region [ PostalCode ]
        /// <summary>Gets/sets zip code.</summary>
        [XmlAttribute("PostalCode")]
        public string PostalCode
        {
            get { return BaseGet<string>("postalcode"); }
            set { SetProperty("postalcode", value); }
        }
        #endregion

        #region [ Department ]
        /// <summary>Gets/sets department.</summary>
        [XmlAttribute("Department")]
        public string Department
        {
            get { return BaseGet<string>("department"); }
            set { SetProperty("department", value); }
        }
        #endregion

        #region [ TelephoneNumber ]
        /// <summary>Gets/sets office phone number.</summary>
        [XmlAttribute("TelephoneNumber")]
        public string TelephoneNumber
        {
            get { return BaseGet<string>("telephonenumber"); }
            set { SetProperty("telephonenumber", value); }
        }
        #endregion

        #region [ FaxNumber ]
        /// <summary>Gets/sets fax number.</summary>
        [XmlAttribute("FaxNumber")]
        public string FaxNumber
        {
            get { return BaseGet<string>("facsimiletelephonenumber"); }
            set { SetProperty("facsimiletelephonenumber", value); }
        }
        #endregion

        #region [ HomeNumber ]
        /// <summary>Gets/sets home phone number.</summary>
        [XmlAttribute("HomeNumber")]
        public string HomeNumber
        {
            get { return BaseGet<string>("homephone"); }
            set { SetProperty("homephone", value); }
        }
        #endregion

        #region [ PagerNumber ]
        /// <summary>Gets/sets page phone number.</summary>
        [XmlAttribute("PagerNumber")]
        public string PagerNumber
        {
            get { return BaseGet<string>("pager"); }
            set { SetProperty("pager", value); }
        }
        #endregion

        #region [ MobileNumber ]
        /// <summary>Gets/sets mobile phone number.</summary>
        [XmlAttribute("MobileNumber")]
        public string MobileNumber
        {
            get { return BaseGet<string>("mobile"); }
            set { SetProperty("mobile", value); }
        }
        #endregion
        #endregion
    }
}
